﻿/// <summary>
/// FileName: ExpressionParsing.cs
/// Author: Jiang Xiaolong
/// Created Time: 2015.05.05
/// Version: 1.0
/// Company: Sunnytech
/// Function: 公式解析；
///
/// Changed By:
/// Modification Time:
/// Discription:
/// </summary>

using System.Collections.Generic;
using Expression.api;

namespace Expression.impl
{
	//实际解析
	public class ExpressionParsing
	{
		//作用域，控制变量
		private static Scope _scope;
		//分词器
		private static Tokenizer _tokenizer;
		//括号对识别
		private static Dictionary<string, string> _bracketPair = new Dictionary<string, string>();
		//运算符优先级识别
		private static Dictionary<string, int> _getPriority = new Dictionary<string, int>();
		/// <summary>
		/// 当前公式解析错误列表；
		/// </summary>
		public static List<ParseError> Errors = new List<ParseError>();
		//当前公式名
		private static string _expName = "";

		static ExpressionParsing()
		{
			//自定义函数注册
			CustomFunctions.Add("sin", new SIN());
			CustomFunctions.Add("asin", new ASIN());
			CustomFunctions.Add("cos", new COS());
			CustomFunctions.Add("acos", new ACOS());
			CustomFunctions.Add("tan", new TAN());
			CustomFunctions.Add("atan", new ATAN());
			CustomFunctions.Add("pow", new POW());
			CustomFunctions.Add("ln", new LN());
			CustomFunctions.Add("lg", new LG());
			CustomFunctions.Add("log", new LOG());
			CustomFunctions.Add("sqrt", new SQRT());
			CustomFunctions.Add("abs", new ABS());
			CustomFunctions.Add("random", new RANDOM());

			_bracketPair.Add("(", ")");
			_bracketPair.Add("[", "]");
			_bracketPair.Add("{", "}");
			_bracketPair.Add("（", "）");
			_bracketPair.Add("【", "】");
			_getPriority.Add("(", 1); _getPriority.Add("（", 1); _getPriority.Add("[", 1); _getPriority.Add("{", 1); _getPriority.Add("【", 1);
			_getPriority.Add("!", 2); _getPriority.Add("！", 2);  //TODO
			_getPriority.Add("^", 3); _getPriority.Add("**", 3);
			_getPriority.Add("/", 4); _getPriority.Add("*", 4); _getPriority.Add("%", 4);
			_getPriority.Add("+", 5); _getPriority.Add("-", 5);
			_getPriority.Add(">", 6); _getPriority.Add("<", 6); _getPriority.Add(">=", 6); _getPriority.Add("<=", 6); _getPriority.Add("==", 6); _getPriority.Add("!=", 6); _getPriority.Add("！=", 6);
			_getPriority.Add("&&", 7); _getPriority.Add("||", 7);
			_getPriority.Add("=", 8);
			//_getPriority.Add("+=", 8);_getPriority.Add("-=", 8);_getPriority.Add("*=", 8);_getPriority.Add("/=", 8);_getPriority.Add("%=", 8);
			_getPriority.Add(",", 9); _getPriority.Add("，", 9);
		}

		/// <summary>
		/// 表达式树解析生成；
		/// </summary>
		/// <param name="name_id">当前公式名；</param>
		/// <param name="input_exp">输入的表达式字符串；</param>
		/// <param name="scope">变量作用域；</param>
		/// <returns>表达式树；</returns>
		public static ExpressionTree Parsing(string name_id, string input_exp, Scope scope)
		{
			_expName = name_id;
			_scope = scope;
			_tokenizer = new Tokenizer(input_exp);
			Errors.Clear();
			return Parsing();
		}

		/// <summary>
		/// 具体解析入口；
		/// </summary>
		/// <returns>表达式树；</returns>
		private static ExpressionTree Parsing()
		{
			ExpressionTree resultExp = BuildExpression();

			if (!_tokenizer.current().IsEnd())
			{
				_tokenizer.AddError(_tokenizer.current(), "未定义字符：" + _tokenizer.current().GetSource() + "！");
				_tokenizer.consume();
			}

			Errors = _tokenizer.GetProblemCollector();

			return resultExp;
		}

		public static List<ParseError> GetProblemCollector()
		{
			return _tokenizer.GetProblemCollector();
		}

		//生成表达式
		private static ExpressionTree BuildExpression()
		{
			ExpressionTree left = RelationalExp();
			if (_tokenizer.current().IsOperator("&&"))
			{
				_tokenizer.consume();
				ExpressionTree right = BuildExpression();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.And);
			}
			if (_tokenizer.current().IsOperator("||"))
			{
				_tokenizer.consume();
				ExpressionTree right = BuildExpression();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Or);
			}
			return left;
		}

		//关系型
		private static ExpressionTree RelationalExp()
		{
			ExpressionTree left = AlgebraExp();
			if (_tokenizer.current().IsOperator("<"))
			{
				_tokenizer.consume();
				ExpressionTree right = RelationalExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.LT);
			}
			if (_tokenizer.current().IsOperator("<="))
			{
				_tokenizer.consume();
				ExpressionTree right = RelationalExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.LT_EQ);
			}
			if (_tokenizer.current().IsOperator("=="))
			{
				_tokenizer.consume();
				ExpressionTree right = RelationalExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.EQ);
			}
			if (_tokenizer.current().IsOperator(">="))
			{
				_tokenizer.consume();
				ExpressionTree right = RelationalExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.GT_EQ);
			}
			if (_tokenizer.current().IsOperator(">"))
			{
				_tokenizer.consume();
				ExpressionTree right = RelationalExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.GT);
			}
			if (_tokenizer.current().IsOperator("!="))
			{
				_tokenizer.consume();
				ExpressionTree right = RelationalExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.NEQ);
			}
			return left;
		}

		//加减代数运算；
		private static ExpressionTree AlgebraExp()
		{
			ExpressionTree left = ProductExp();
			if (_tokenizer.current().IsOperator("+"))
			{
				_tokenizer.consume();
				ExpressionTree right = AlgebraExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Add);
			}
			if (_tokenizer.current().IsOperator("-"))
			{
				_tokenizer.consume();
				ExpressionTree right = AlgebraExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Subtract);
			}
			return left;
		}

		//乘除和取余运算；
		private static ExpressionTree ProductExp()
		{
			ExpressionTree left = ExponentExp();
			if (_tokenizer.current().IsOperator("*"))
			{
				_tokenizer.consume();
				ExpressionTree right = ProductExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Multiply);
			}
			if (_tokenizer.current().IsOperator("/"))
			{
				_tokenizer.consume();
				ExpressionTree right = ProductExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Divide);
			}
			if (_tokenizer.current().IsOperator("%"))
			{
				_tokenizer.consume();
				ExpressionTree right = ProductExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Modulo);
			}
			return left;
		}

		//指数运算；
		private static ExpressionTree ExponentExp()
		{
			ExpressionTree left = OppositeExp();
			if (_tokenizer.current().IsOperator("^") || _tokenizer.current().IsOperator("**"))
			{
				_tokenizer.consume();
				ExpressionTree right = ExponentExp();
                return ReOrder(left, right, BinaryExpression.BinaryOperator.Power);
			}
			return left;
		}

		//取非运算；
		private static ExpressionTree OppositeExp()
		{
			ExpressionTree left = AtomExp();
			if (_tokenizer.current().IsOperator("!") || _tokenizer.current().IsOperator("！"))
			{
				left = new BinaryExpression(left, left, BinaryExpression.BinaryOperator.Not);
			}
			return left;
		}

        /// <summary>
        /// 同样优先级的二元运算交换顺序，以使计算顺序符合要求；
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="op"></param>
        /// <returns></returns>
        private static ExpressionTree ReOrder (ExpressionTree left, ExpressionTree right, BinaryExpression.BinaryOperator op)
        {
            if (right.GetType() == typeof(BinaryExpression))
            {
                BinaryExpression rightOp = (BinaryExpression)right;
                if (!rightOp.IsSealed() && rightOp.GetPriority() == rightOp.GetPriority(op))
                {
                    ReplaceLeft(rightOp, left, op);
                    return right;
                }
            }
            //UnityEngine.Debug.LogWarning("ReOrder");
            return new BinaryExpression(left, right, op);
        }

        private static void ReplaceLeft (BinaryExpression target, ExpressionTree newLeft, BinaryExpression.BinaryOperator op)
        {
            if (target.GetLeftExp().GetType() == typeof(BinaryExpression))
            {
                BinaryExpression leftOp = (BinaryExpression)target.GetLeftExp();
                if (!leftOp.IsSealed() && leftOp.GetPriority() == leftOp.GetPriority(op))
                {
                    ReplaceLeft(leftOp, newLeft, op);
                    return;
                }
            }
            //UnityEngine.Debug.LogWarning( "ReplaceLeft" );
            target.SetLeftExp(new BinaryExpression(newLeft, target.GetLeftExp(), op));
        }


		/// <summary>
		/// 最小公式；
		/// </summary>
		/// <returns>当前公式；</returns>
		private static ExpressionTree AtomExp()
		{
			if (_tokenizer.current().IsOperator("-"))  //处理起始为“-”
			{
				_tokenizer.consume();
				BinaryExpression result = new BinaryExpression(new ConstantExpression(0, typeof(int)), AtomExp(), BinaryExpression.BinaryOperator.Subtract);
				result.SetSeal();
				return result;
			}
			if (_tokenizer.current().IsOperator("+") && _tokenizer.next().IsStartBracket())  //忽略最前面的“+”
			{
				_tokenizer.consume();
			}
			if (_tokenizer.current().IsOperator("+") && _tokenizer.next().IsConstant())  //忽略最前面的“+”
			{
				_tokenizer.consume();
			}
			if (_tokenizer.current().IsOperator("+") && _tokenizer.next().IsIdentifier())  //忽略最前面的“+”
			{
				_tokenizer.consume();
			}
			if (_tokenizer.current().IsStartBracket())  //括号开始
			{
				string endBracket = _bracketPair[_tokenizer.consume().GetTrigger()];
				ExpressionTree result = BuildExpression();
				if (result.GetType() == typeof(BinaryExpression))
				{
					((BinaryExpression)result).SetSeal();
				}
				ExpectTrigger(Token.TokenType.OPERATOR, endBracket);  //括号结束处理
				return result;
			}
			if (_tokenizer.current().IsConstant())  //一些常量
			{
				object value = null;
				if (_tokenizer.current().IsBool())
				{
					value = bool.Parse(_tokenizer.current().GetContents());
				}
				else if (_tokenizer.current().IsDouble())
				{
					value = double.Parse(_tokenizer.current().GetContents());
				}
				else if (_tokenizer.current().IsFloat())
				{
					value = float.Parse(_tokenizer.current().GetContents());
				}
				else if (_tokenizer.current().IsInteger())
				{
					value = int.Parse(_tokenizer.current().GetContents());
				}
				else
				{
					value = _tokenizer.current().GetContents();
				}
				ExpressionTree constantExp = new ConstantExpression(value, _tokenizer.consume().type);
				return constantExp;
			}
			if (_tokenizer.current().IsIdentifier())  //变量或函数处理
			{
				if (_tokenizer.next().IsStartBracket())  //自定义函数
				{
					//应该用递归的方式把函数算出来，当一个值处理，在这里做一全套的
					string endStart = _bracketPair[_tokenizer.next().GetTrigger()];
					return FunctionCall(endStart);
				}
				else  //变量
				{
					Variable varValue = _scope.Find(_tokenizer.current().GetContents());
					if (varValue == null)
					{
						if (ExpressionManager.IsCreatedExpression(_tokenizer.current().GetContents()))
						{
							ExpressionManager.VarExpRelation(_expName, _tokenizer.current().GetContents());
                            ExpressionTree cloneExp = ExpressionManager.GetExpression(_tokenizer.consume().GetContents()).Clone();
                            if (cloneExp.GetType() == typeof(BinaryExpression))
                            {
                                ( (BinaryExpression)cloneExp ).SetSeal();
                            }
                            return cloneExp;
						}
						_tokenizer.AddError(_tokenizer.current(), "变量名：" + _tokenizer.current().GetContents() + "，该变量在变量作用域中未定义，也未定义该表达式，无法识别!");
						_tokenizer.consume();
						return ConstantExpression.Empty();
					}
					else
					{
						ExpressionManager.VarExpRelation(_expName, _tokenizer.consume().GetContents());
						return new VariableExpression(varValue);
					}
				}
			}
			if (_tokenizer.current().IsKeyword())  //关键字处理
			{
				//暂时没有
				_tokenizer.AddError(_tokenizer.current(), "关键词ID：" + _tokenizer.current().GetSource() + "暂时未定义！");
				_tokenizer.consume();
				return ConstantExpression.Empty();
			}
			if (_tokenizer.current().IsSpecialIdentifier())
			{
				//暂时没有
				_tokenizer.AddError(_tokenizer.current(), "特殊ID: " + _tokenizer.current().GetSource() + "暂时未定义！");
				_tokenizer.consume();
				return ConstantExpression.Empty();
			}

			_tokenizer.AddError(_tokenizer.current(), "检测到无效字符: " + _tokenizer.current().GetSource() + "！");
			_tokenizer.consume();

			return ConstantExpression.Empty();
		}

		//函数处理
		private static ExpressionTree FunctionCall(string end_bracket)
		{
			FunctionExpression call = new FunctionExpression();
			Token funToken = _tokenizer.consume();
			ICustomFunction fun = CustomFunctions.Find(funToken.GetContents());
			if (fun == null)
			{
				_tokenizer.AddError(funToken, "未定义函数：" + funToken.GetContents() + "！");
			}
			call.SetFunction(fun);
			_tokenizer.consume().GetTrigger(); //消除（
			while (!_tokenizer.current().IsOperator(end_bracket) && !_tokenizer.current().IsEnd())
			{
				if (call.ParameterCount() != 0)
				{
					ExpectTrigger(Token.TokenType.OPERATOR, ",");
				}
				call.AddParameter(BuildExpression());
			}
			ExpectTrigger(Token.TokenType.OPERATOR, end_bracket);
			if (fun == null)
			{
				return ConstantExpression.Empty();
			}
            call.Evaluate();  //计算一遍，确定类型
			if (call.ParameterCount() != fun.ParameterNumber() && fun.ParameterNumber() >= 0)
			{
				_tokenizer.AddError(funToken, "函数参数不一致，当前函数：" + funToken.GetContents() + "，规定参数个数：" + fun.ParameterNumber() + "，当前参数个数：" + call.ParameterCount() + "！");
				return ConstantExpression.Empty();
			}
			return call;
		}

		//消除“）”等后缀；
		private static void ExpectTrigger(Token.TokenType type, string trigger)
		{
			if (_tokenizer.current().Matches(type, trigger))
			{
				_tokenizer.consume();
			}
			else
			{
				_tokenizer.AddError(_tokenizer.current(), "期望获得 " + trigger + "，当前值为 " + _tokenizer.current().GetTrigger() + "！");
			}
		}

	}
}

